package simulation;

import streaming.StreamingConfig;
import cern.jet.random.Normal;
import cern.jet.random.Poisson;
import cern.jet.random.engine.RandomEngine;

public class Distributions {

	Poisson poisson;
	Normal normal;
	RandomEngine re = RandomEngine.makeDefault();
	DistributionAction distributionAction;
	
	public Distributions(DistributionAction da , DistributionEnum de){
		this.distributionAction = da;
		
		switch (this.distributionAction){
			case INSERTION:
				switch (de) {
					case NORMAL:
						this.normal = new Normal(StreamingConfig.NORMAL_INSERTION_MEAN, StreamingConfig.NORMAL_INSERTION_STANDARD_DEVIATION, re);
					break;
					case POISSON:
						this.poisson = new Poisson(StreamingConfig.POISSON_INSERTION_MEAN, re);
					break;
				}
			break;
			case REMOVAL:
				switch (de) {
					case NORMAL:
						this.normal = new Normal(StreamingConfig.NORMAL_REMOVAL_MEAN, StreamingConfig.NORMAL_REMOVAL_STANDARD_DEVIATION, re);
					break;
					case POISSON:
						this.poisson = new Poisson(StreamingConfig.POISSON_REMOVAL_MEAN, re);
					break;
				}
			break;	
		}
	}
	
	public Poisson getPoisson() {
		return poisson;
	}

	public void setPoisson(Poisson poisson) {
		this.poisson = poisson;
	}

	public Normal getNormal() {
		return normal;
	}

	public void setNormal(Normal normal) {
		this.normal = normal;
	}

	/**
	 * Gets next double value generated by distribution
	 * @return The next double value estimated by distribution selected
	 */
	public double getNextDouble(){
		double value = 0.0;
		
		switch (this.distributionAction){
			case INSERTION:
				switch (StreamingConfig.INSERTION_DISTRIBUTION_TYPE) {
					case NORMAL:
						value = normal.nextDouble();
					break;
					case POISSON:
						value =  poisson.nextDouble();
					break;
				}
			break;
			case REMOVAL:
				switch (StreamingConfig.REMOVAL_DISTRIBUTION_TYPE) {
					case NORMAL:
						value =  normal.nextDouble();
					break;
					case POISSON:
						value =  poisson.nextDouble();
					break;
				}
			break;
		}
		// If value is negative, invert signal
		if (value < 0){
			value *= -1.0;
		}
		
		return value;
	}
	
	/**
	 * Gets next int value generated by distribution
	 * @return
	 */
	public int getNextInt(){
		int value = 0;
		
		switch (this.distributionAction){
			case INSERTION:
				switch (StreamingConfig.INSERTION_DISTRIBUTION_TYPE) {
					case NORMAL:
						value = normal.nextInt();
					break;
					case POISSON:
						value =  poisson.nextInt();
					break;
				}
			break;
			case REMOVAL:
				switch (StreamingConfig.REMOVAL_DISTRIBUTION_TYPE) {
					case NORMAL:
						value =  normal.nextInt();
					break;
					case POISSON:
						value =  poisson.nextInt();
					break;
				}
			break;
		}
		// If value is negative, invert signal
		if (value < 0){
			value *= -1;
		}
		
		return value;
	}
}
